package com.chebaohui.iqs.service.impl.deal.libao.profess;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.chebaohui.iqs.config.CompanyCode;
import com.chebaohui.iqs.config.CompanyValue;
import com.chebaohui.iqs.config.InsuranceCode;
import com.chebaohui.iqs.config.ResultCode;
import com.chebaohui.iqs.entity.base.CarOrder;
import com.chebaohui.iqs.entity.base.Insurance;
import com.chebaohui.iqs.entity.db.DbParam;
import com.chebaohui.iqs.entity.req.CarPrice;
import com.chebaohui.iqs.entity.res.CompanyCarPrice;
import com.chebaohui.iqs.sdk.chaojiying.ChaoJiYingSdk;
import com.chebaohui.iqs.service.impl.deal.libao.sdk.LibaoRequest;
import com.chebaohui.iqs.service.impl.deal.libao.util.LibaoConfig;
import com.chebaohui.iqs.service.impl.deal.libao.util.ParamtenGet;
import com.chebaohui.iqs.service.impl.deal.libao.util.PublicParam;
import com.chebaohui.iqs.service.impl.deal.util.StringUtil;
import com.chebaohui.iqs.service.impl.deal.util.TimeBase;

/**
 * 利宝车险算费
 * 
 * @author regas_xie
 *
 */
public class LbCarPrice {
	/**
	 * log:日志输出
	 */
	private Log log = LogFactory.getLog(LbCarPrice.class);

	private Map<String, String> map;

	private CompanyCarPrice result;// 报价记录

	private CarPrice param;

	private String carCode;
	private ParamtenGet paramten;

	public LbCarPrice(CarPrice param, String carCode) {
		this.result = new CompanyCarPrice();
		this.param = param;
		this.carCode = carCode;
		result.setCompanyCode(CompanyCode.LIBAO.getCode());
		result.setModelCode(carCode);
		result.setCode(ResultCode.SUCCESS.getCode());
		result.setMsg(ResultCode.SUCCESS.getMsg());
	}

	/**
	 * 获取sql缓存数据
	 * 
	 * @return
	 * @throws Exception
	 */
	public DbParam getMap() throws Exception {
		DbParam dbParam = new DbParam();
		dbParam.setcType("insurance");
		dbParam.setNumType("json");
		dbParam.setReserve(resJson.getJSONObject("result").getString("flowId"));
		dbParam.setSpare(TimeBase.getDay("yyyy-MM-dd HH:mm:ss", 0));
		dbParam.setDatas(PublicParam.getParam(map).toJSONString());
		return dbParam;
	}

	private void defaultSet() throws Exception {
		this.map = PublicParam.getParam();
		if (StringUtil.isNulls(map.get("access_token"))) {
			throw new Exception("利宝token认证获取失败");
		}

		this.paramten = new ParamtenGet(param, getCar());
	}

	private void setParamtenTime() throws Exception {
		if(StringUtil.isNulls(resJson.getJSONObject("result").getString("resultMessage")))
			return ;
		if (dealTime(resJson.getJSONObject("result").getString("resultMessage"))) {
			resJson = JSONObject.parseObject(price(paramten));
			if (!resJson.getBoolean("success")) {
				if (dealTime(resJson.getJSONObject("result").getString("resultMessage"))) {
					resJson = JSONObject.parseObject(price(paramten));
				}
			}
		}
	}

	private JSONObject resJson;

	/**
	 * 利宝直连接口报价
	 * 
	 * @return
	 */
	public CompanyCarPrice price() {
		log.info("进入" + CompanyValue.LIBAO + "车险报价-" + param.getLicense().getLicenceNo() + "....");
		try {
			defaultSet();

			this.resJson = JSONObject.parseObject(price(paramten));
 
			for(int p=0;p<6;p++){
				setParamtenTime();

				if (dealRenewal())
					resJson = JSONObject.parseObject(renewalPrice());
				//log.info("......."+p);
			}

			if(!"0".equals(resJson.getJSONObject("result").getString("resultCode"))){
				if(!resJson.getJSONObject("result").getBooleanValue("status"))
					return new CompanyCarPrice(CompanyCode.LIBAO.getCode(), carCode, ResultCode.N04.getCode(),
							ResultCode.N04.getMsg() + resJson.getString("resCode") + ":"
									+ resJson.getJSONObject("result").getString("resultMessage"));
			}

			dealRes(resJson, paramten);

			return result;
		} catch (Exception e) {
			log.error(CompanyValue.LIBAO + "车险报价" + param.getLicense().getLicenceNo() + "过程过程异常:" + e.getMessage());
			return new CompanyCarPrice(CompanyCode.LIBAO.getCode(), carCode, ResultCode.N02.getCode(),
					ResultCode.N02.getMsg() + "车险报价过程异常:" + e.getMessage());
		} finally {
			log.info(CompanyValue.LIBAO + "车险报价" + param.getLicense().getLicenceNo() + "结束。");
		}
	}

	private boolean dealTime(String resultMessage) throws Exception {
		boolean b = false, t = false;
		if (resultMessage.indexOf("重复投保") >= 0) {
			if (resultMessage.indexOf("交强险") >= 0) {
				if (resultMessage.indexOf("终保日期") > 0) {
					String s = resultMessage.substring(resultMessage.indexOf("终保日期") + 4);
					if(s.indexOf(":")==0)
						s=s.substring(1);
					if(s.indexOf(":")>0)
						s=s.substring(0,s.indexOf(":")).trim();
					if(s.indexOf(";")>0)
						s=s.substring(0,s.indexOf(";")).trim();
					if (valTime(s)) {
						String[] list = s.split(" ");
						if (list.length == 2) {
							paramten.setTraTimeStart(list[0].trim(), 0/*Integer.valueOf(list[1].trim())*/);
							t = true;
						}
					}
				}
			}
			if (resultMessage.indexOf("商业险") >= 0) {
				if (resultMessage.indexOf("终保日期") >= 0) {
					String s = resultMessage.substring(resultMessage.indexOf("终保日期") + 4);
					if(s.indexOf(":")==0)
						s=s.substring(1);
					if(s.indexOf(":")>0)
						s=s.substring(0,s.indexOf(":")).trim();
					if(s.indexOf(";")>0)
						s=s.substring(0,s.indexOf(";")).trim();
					if (valTime(s)) {
						String[] list = s.split(" ");
						if (list.length == 2) {
							paramten.setBusTimeStart(list[0].trim(), Integer.valueOf(list[1].trim()));
							b = true;
						}
					}
				}
			}
		}
		if (b || t) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 时间判断
	 * 
	 * @return
	 */
	public static boolean valTime(String time) {
		if (StringUtil.isNulls(time))
			return false;
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH");
			Date date = sdf.parse(time);
			return sdf.format(date).equals(time);
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 报价请求
	 * 
	 * @param paramten
	 * @return
	 * @throws Exception
	 */
	private String price(ParamtenGet paramten) throws Exception {
		JSONObject json = PublicParam.getParam(map);
		// 投保单信息
		JSONObject tprpTmainDto = paramten.getTprpTmainDto();
		map.put("proposalNo", StringUtil.isNulls(tprpTmainDto.getString("proposalNo")) ? "NULL"
				: tprpTmainDto.getString("proposalNo"));
		map.put("mtplProposalNo", StringUtil.isNulls(tprpTmainDto.getString("mtplProposalNo")) ? "NULL"
				: tprpTmainDto.getString("mtplProposalNo"));

		map.put("combineFlag", tprpTmainDto.getString("combineFlag"));
		// 投保标的信息
		JSONObject tprpTitemCarDto = paramten.getTprpTitemCarDto();
		map.put("engineNo", tprpTitemCarDto.getString("engineNo"));
		map.put("vinNo", tprpTitemCarDto.getString("vinNo"));
		map.put("modelCode", tprpTitemCarDto.getString("modelCode"));
		json.put("pdk", PublicParam.getPdk(md5Map()));

		json.put("tprpTmainDto", tprpTmainDto);
		json.put("tprpTitemCarDto", tprpTitemCarDto);
		json.put("tprptCarOwnerDto", paramten.getTprptCarOwnerDto());// 车主信息
		json.put("tprptApplicantDto", paramten.getTprptApplicantDto());// 投保人信息
		json.put("tprptInsuredDto", paramten.getTprptInsuredDto());// 被保险人信息
		json.put("tprpTitemKindListDto", paramten.getTprpTitemKindListDto());// 险别选择信息List

		String res = LibaoRequest.post(
				LibaoConfig.libao_url + "/calculate/combinecalculate?access_token=" + map.get("access_token"),
				json.toJSONString());
		log.info(CompanyValue.LIBAO + "报价-" + param.getLicense().getLicenceNo() + ":" + "\n" + "请求路径:"
				+ LibaoConfig.libao_url + "/calculate/combinecalculate?access_token=" + map.get("access_token") + "\n"
				+ "请求参数:" + json.toJSONString() + "\n" + "请求返回:" + res);
		if (StringUtil.isNulls(res)) {
			throw new Exception("请求返回空");
		}
		return res;
	}

	/**
	 * 转保判断
	 * 
	 * @param resJson
	 * @return
	 * @throws Exception
	 */
	private boolean dealRenewal() throws Exception {
		if(StringUtil.isNulls(resJson.getJSONObject("result").getString("renewalQuestion")))
			return false;
		if (resJson.getJSONObject("result").getString("renewalQuestion").length() > 0)
			return true;
		else
			return false;
	}

	/**
	 * 转保再次算费请求返回空
	 * 
	 * @param resJson
	 * @return
	 * @throws Exception
	 */
	private String renewalPrice() throws Exception {
		JSONObject renewal = new JSONObject();
		renewal.put("partnerAccountCode", map.get("partnerAccountCode"));
		renewal.put("flowId", map.get("flowId"));
		renewal.put("operatorDate", map.get("operatorDate"));
		renewal.put("recordCode", map.get("recordCode"));
		renewal.put("agreementNo", map.get("agreementNo"));
		// renewal.put("pdk", "");
		renewal.put("renewalFlag", resJson.getJSONObject("result").getString("renewalFlag"));
		renewal.put("querySequenceNo", resJson.getJSONObject("result").getString("querySequenceNo"));
		Map<String, String> identify = ChaoJiYingSdk
				.identifyBase64Img(resJson.getJSONObject("result").getString("renewalQuestion"));
		if (!"true".equals(identify.get("state"))) {
			throw new Exception("利宝车险验证码工具识别错误:" + identify.get("msg"));
		}
		renewal.put("answer", identify.get("data"));

		//		try {
		//			Thread.sleep(1000);
		//		} catch (Exception e) {
		//			e.printStackTrace();
		//		}

		String res = LibaoRequest.post(
				LibaoConfig.libao_url + "/calculate/verify?access_token=" + map.get("access_token"),
				renewal.toJSONString());

		log.info(CompanyValue.LIBAO + "报价-" + param.getLicense().getLicenceNo() + ":" + "\n" + "请求路径:"
				+ LibaoConfig.libao_url + "/calculate/verify?access_token=" + map.get("access_token") + "\n" + "请求参数:"
				+ renewal.toJSONString() + "\n" + "请求返回:" + res);

		if (StringUtil.isNulls(res))
			throw new Exception("转保再次算费请求返回空");

		return res;
	}

	/**
	 * 处理返回结果
	 * 
	 * @param prices
	 * @return
	 * @throws Exception
	 */
	private void dealRes(JSONObject prices, ParamtenGet paramten) throws Exception {
		JSONObject tprpTmainDto = prices.getJSONObject("result").getJSONObject("tprpTmainDto");

		CarOrder order = new CarOrder();
		order.setOrederNo(prices.getJSONObject("result").getString("flowId"));

		List<Insurance> ins = new ArrayList<>();

		String renewal = "";
		if ("1".equals(tprpTmainDto.getString("renewalFlag"))) {
			renewal = "0";
		} else if ("0".equals(tprpTmainDto.getString("renewalFlag"))) {
			renewal = "1";
		} else {
			renewal = "2";
		}

		BigDecimal total = new BigDecimal(prices.getJSONObject("result").getString("subPremium"));

		if (paramten.isBus()) {
			order.setBusNo(tprpTmainDto.getString("proposalNo"));
			order.setBusTotalPrice(tprpTmainDto.getString("premium"));

			order.setBusBeginTime(
					tprpTmainDto.getString("startDate") + (tprpTmainDto.getIntValue("startHour") > 9 ? " " : " 0")
					+ tprpTmainDto.getIntValue("startHour") + ":00:00");

			int bHour=tprpTmainDto.getIntValue("endHour");
			if(bHour>0)
				bHour=bHour-1;
			order.setBusEndTime(
					tprpTmainDto.getString("endDate") + (bHour > 9 ? " " : " 0")
					+ bHour + ":59:59");
			order.setBusRenewal(renewal);

			JSONArray tprpTitemKindListDto = prices.getJSONObject("result").getJSONArray("tprpTitemKindListDto");
			JSONArray zhu = new JSONArray();
			JSONArray chi = new JSONArray();
			for (int i = 0; i < tprpTitemKindListDto.size(); i++) {
				if (checkResIns(tprpTitemKindListDto.getJSONObject(i).getString("kindCodeMain")) == 1)
					zhu.add(tprpTitemKindListDto.getJSONObject(i));
				else
					chi.add(tprpTitemKindListDto.getJSONObject(i));
			}

			for (int i = 0; i < zhu.size(); i++) {
				ins.add(getResIns(zhu.getJSONObject(i), chi));
			}
		}

		if (paramten.isTra()) {
			order.setTraNo(tprpTmainDto.getString("mtplProposalNo"));
			order.setTraPrice(tprpTmainDto.getString("mtplPremium"));
			order.setTraRenewal(renewal);
			order.setTraBeginTime(tprpTmainDto.getString("mtplStartDate")
					+ (tprpTmainDto.getIntValue("mtplStartHour") > 9 ? " " : " 0")
					+ tprpTmainDto.getIntValue("mtplStartHour") + ":00:00");

			int bHour=tprpTmainDto.getIntValue("mtplEndHour");
			if(bHour>0)
				bHour=bHour-1;
			order.setTraEndTime(
					tprpTmainDto.getString("mtplEndDate") + (bHour > 9 ? " " : " 0")
					+ bHour + ":59:59");

			String tax = prices.getJSONObject("result").getJSONObject("prpTcarshipTaxDto").getString("sumTax");
			total = total.add(new BigDecimal(tax));
			order.setTaxPrice(tax);
			if(!paramten.isBus()){
				JSONArray tprpTitemKindListDt = prices.getJSONObject("result").getJSONArray("tprpTitemKindListDto");
				JSONArray zhu = new JSONArray();
				JSONArray chi = new JSONArray();
				for (int i = 0; i < tprpTitemKindListDt.size(); i++) {
					if (checkResIns(tprpTitemKindListDt.getJSONObject(i).getString("kindCodeMain")) == 1)
						zhu.add(tprpTitemKindListDt.getJSONObject(i));
					else
						chi.add(tprpTitemKindListDt.getJSONObject(i));
				}

				for (int i = 0; i < zhu.size(); i++) {
					ins.add(getResIns(zhu.getJSONObject(i), chi));
				}
			}

		}else{
			order.setTraPrice("0");
			order.setTaxPrice("0");
			JSONObject z=new JSONObject();
			z.put("premiumMain", "0");
			ins.add(getResInsView(InsuranceCode.TP, z, null));
		}

		order.setTotalCarPrice(total.toString());
		map.put("timeLongTo", "" + new Date().getTime());
		result.setCarOrder(order);
		result.setInsuranceList(ins);
	}

	/**
	 * 获取返回商业险详情列表
	 * 
	 * @param z
	 * @param chi
	 * @return
	 */
	private Insurance getResIns(JSONObject z, JSONArray chi) throws Exception {
		switch (z.getString("kindCodeMain")) {
		case "A200":// 机车损失险
			return getResInsView(InsuranceCode.BL, z, getResInsChi(chi, "A911"));
		case "A500":// 盗抢险
			return getResInsView(InsuranceCode.BT, z, getResInsChi(chi, "A921"));
		case "A600":// 第三责任险
			return getResInsView(InsuranceCode.BTR, z, getResInsChi(chi, "A912"));
		case "A701":// 车上人员(司机)责任险
			return getResInsView(InsuranceCode.BD, z, getResInsChi(chi, "A928"));
		case "A702":// 车上人员(乘客)责任险
			return getResInsView(InsuranceCode.BP, z, getResInsChi(chi, "A929"));
		case "A210":// 车身划痕损失险
			return getResInsView(InsuranceCode.BN, z, getResInsChi(chi, "A971"));
		case "A231":// 玻璃单独破碎险
			return getResInsView(InsuranceCode.BG, z, null);
		case "BZ"://交强险
			return getResInsView(InsuranceCode.TP, z, null);
		case "A252":// 指定修理厂险
			return getResInsView(InsuranceCode.BR, z, null);
		case "A310":// 自燃损失险
			return getResInsView(InsuranceCode.BNP, z, getResInsChi(chi, "A970"));
		case "A290":// 发动机涉水损失险
			return getResInsView(InsuranceCode.BW, z, getResInsChi(chi, "A972"));
		case "A250":// 第三方特约险
			return getResInsView(InsuranceCode.BTT, z, getResInsChi(chi, "A250"));
		default:
			throw new Exception("返回车险中主险编码出现错误:" + z.getString("kindCodeMain"));
		}
	}

	/**
	 * 获取详细列表
	 * 
	 * @param ic
	 *            车险编码
	 * @param pri
	 *            保费
	 * @param ind
	 *            不计免赔费用
	 * @param amount
	 *            保额
	 * @param pate
	 *            费率
	 * @param type
	 *            类型
	 * @return
	 */
	private Insurance getResInsView(InsuranceCode ic, JSONObject z, JSONObject c) {
		Insurance ins = new Insurance();
		ins.setCode(ic.getCode());
		if (ic.getCode().equals(InsuranceCode.BP.getCode())) {
			if (StringUtil.isNulls(z.getString("unitAmountMain"))) {
				ins.setAuount("0");
			} else {
				ins.setAuount(z.getString("unitAmountMain"));
			}
		} else {
			if (StringUtil.isNulls(z.getString("amountMain"))) {//amountMain
				ins.setAuount("0");
			} else {
				ins.setAuount(z.getString("amountMain"));
			}
		}

		if (ic.getCode().equals(InsuranceCode.BG.getCode())) {
			if ("2".equals(z.getString("modeCode")))
				ins.setType("01");
			else
				ins.setType("00");
		} else if (ic.getCode().equals(InsuranceCode.BR.getCode())) {
			ins.setPate(z.getString("unitAmountMain"));
			ins.setType("00");
		} else {
			ins.setPate("30");
			ins.setType("00");
		}

		ins.setValue(ic.getValue());

		ins.setInsurancePrice(z.getString("premiumMain"));

		if (null != c) {
			ins.setIndemnityPrice(c.getString("premiumMain"));
			ins.setIndemnity("true");
		} else {
			ins.setIndemnity("false");
			ins.setIndemnityPrice("0");
		}

		return ins;
	}

	/**
	 * 获取不计免赔详细
	 * 
	 * @param chi
	 * @param code
	 * @return
	 */
	private JSONObject getResInsChi(JSONArray chi, String code) {
		if (null == chi || chi.isEmpty())
			return null;
		for (int i = 0; i < chi.size(); i++) {
			if (code.equals(chi.getJSONObject(i).getString("kindCodeMain")))
				return chi.getJSONObject(i);
		}
		return null;
	}

	/**
	 * 找出主险还是不计免赔
	 * 
	 * @param code
	 * @return
	 * @throws Exception
	 */
	private int checkResIns(String code) throws Exception {
		String[] zl = { "A200", "A500", "A600", "A701", "A702", "A210", "A231", "A252", "A310", "A290","A250","BZ" };
		for (String z : zl) {
			if (code.equals(z))
				return 1;
		}
		String[] cl = { "A911", "A921", "A912", "A928", "A929", "A971", "A970", "A972" };
		for (String c : cl) {
			if (code.equals(c))
				return 2;
		}
		throw new Exception("返回车险代码出现错误:" + code);
	}

	/**
	 * 车辆信息获取
	 * 
	 * @param lableNo
	 *            厂牌
	 * @param carCode
	 *            车型编码
	 * @param map
	 * @return
	 * @throws Exception
	 */
	private JSONObject getCar() throws Exception {
		JSONArray motorList = LbCheckCar.checkCar(param.getLicense().getLableNo(), map);
		if (null == motorList || motorList.isEmpty() || motorList.size() < 1)
			throw new Exception("无此厂牌:" + param.getLicense().getLableNo() + "的车辆信息");

		for (int i = 0; i < motorList.size(); i++) {
			if (carCode.equals(motorList.getJSONObject(i).getString("modeCode")))
				return motorList.getJSONObject(i);
		}

		throw new Exception("车型列表中无此:" + carCode + "车型编码的车辆");
	}

	/**
	 * 利宝保费计算接口加密字段获取
	 * 
	 * @param map
	 * @return
	 */
	private Map<String, String> md5Map() {
		Map<String, String> md5 = new HashMap<String, String>();
		md5.put("partnerAccountCode", map.get("partnerAccountCode"));
		md5.put("agreementNo", map.get("agreementNo"));
		md5.put("recordCode", map.get("recordCode"));
		md5.put("flowId", map.get("flowId"));
		md5.put("proposalNo", map.get("proposalNo"));
		md5.put("mtplProposalNo", map.get("mtplProposalNo"));
		md5.put("combineFlag", map.get("combineFlag"));
		md5.put("engineNo", map.get("engineNo"));
		md5.put("vinNo", map.get("vinNo"));
		md5.put("modelCode", map.get("modelCode"));
		return md5;
	}

}
